package permission

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/samber/lo"
	"github.com/spf13/cast"
	"private-domain-overseas-service/admin/business/api/internal/repository/permission"
	"private-domain-overseas-service/pkg/status/bizadmin"
	"private-domain-overseas-service/pkg/xerr"
	"private-domain-overseas-service/tools/ent"
	"private-domain-overseas-service/tools/ent/adminrole"
	"private-domain-overseas-service/tools/ent/adminrouter"
	"private-domain-overseas-service/tools/ent/predicate"
	"strconv"
	"strings"

	"private-domain-overseas-service/admin/business/api/internal/svc"
	"private-domain-overseas-service/admin/business/api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type AdminRouteUserLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// 用户路由接口
func NewAdminRouteUserLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AdminRouteUserLogic {
	return &AdminRouteUserLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *AdminRouteUserLogic) AdminRouteUser() (resp *types.UserRoutesResponse, err error) {
	adminRouterDao := permission.NewAdminRouterDao(l.ctx, l.svcCtx)
	adminRoleDAO := permission.NewAdminRoleDao(l.ctx, l.svcCtx)

	// 从token中获取角色id
	roleIds, roleIdOk := l.ctx.Value("rids").(string)
	if !roleIdOk {
		return nil, xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, "获取用户信息失败")
	}

	// 解析角色id
	var intRoleIds []int
	err = json.Unmarshal([]byte(roleIds), &intRoleIds)
	if err != nil {
		return nil, xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, fmt.Sprintf("角色id转换失败: %v", err.Error()))
	}

	// 根据角色id查询角色
	roleConditions := []predicate.AdminRole{
		adminrole.IDIn(intRoleIds...),
	}
	adminRoles, err := adminRoleDAO.AdminRoleConditionsAll(roleConditions)
	if err != nil {
		return nil, xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, fmt.Sprintf("获取用户角色失败: %v", err.Error()))
	}

	// 取出路由id（二维）
	routerOriginIds := lo.Map(adminRoles, func(item *ent.AdminRole, _ int) []int {
		return lo.Map(strings.Split(item.AdminRoleRouterIds, ","), func(item string, _ int) int {
			id, _ := strconv.Atoi(item)
			return id
		})
	})

	// 二维数组转一维 再去重
	allButtonIds := lo.Flatten(routerOriginIds)
	routerIds := lo.Uniq(allButtonIds)

	// 查询路由
	conditions := make([]predicate.AdminRouter, 0)
	conditions = append(conditions, adminrouter.AdminRouterStatusEQ(bizadmin.StatusEnabled))
	conditions = append(conditions, adminrouter.AdminRouterMenuTypeNotIn(bizadmin.TypeButton))
	conditions = append(conditions, adminrouter.IDIn(routerIds...))
	adminRouters, _, err := adminRouterDao.AdminRouterConditionsAll(conditions)
	if err != nil {
		return nil, xerr.ErrCodeMsg(xerr.ServerOperationExceptionError, fmt.Sprintf("获取用户路由失败: %v", err.Error()))
	}

	// *ent.AdminRouter组装成*types.Route类型
	routes := convertRouterToRoute(adminRouters)

	// 构建用户的路由树
	list := buildRouteTree(routes, 0)

	// 返回数据
	return &types.UserRoutesResponse{
		Routes: list,
	}, nil
}

// *ent.AdminRouter转换成*types.Route
func convertRouterToRoute(routers []*ent.AdminRouter) []*types.Route {
	return lo.Map(routers, func(item *ent.AdminRouter, _ int) *types.Route {
		route := &types.Route{
			Id:       int64(item.ID),
			ParentId: item.AdminRouterPid,
			Name:     item.AdminRouterRouteName,
			Path:     item.AdminRouterRoutePath,
			Meta: types.RouteMeta{
				Title:      item.AdminRouterRouteName,
				I18nKey:    item.AdminRouterI18nKey,
				Icon:       item.AdminRouterIcon,
				Order:      item.AdminRouterOrder,
				HideInMenu: cast.ToBool(item.AdminRouterHideInMenu - 1),
				ActiveMenu: item.AdminRouterActiveMenu,
				MultiTab:   cast.ToBool(item.AdminRouterMultiTab - 1),
				KeepAlive:  cast.ToBool(item.AdminRouterKeepAlive - 1),
				Constant:   cast.ToBool(item.AdminRouterConstant - 1),
				Href:       item.AdminRouterHref,
			},
			Component: item.AdminRouterComponent,
			Redirect:  "",
		}
		if item.AdminRouterComponent == "view.iframe-page" {
			route.Props = map[string]any{
				"url": item.AdminRouterHref,
			}
			route.Meta.Href = ""
		}
		// 如果是系统图标，则使用本地图标
		if item.AdminRouterIconType == bizadmin.SysIcon {
			route.Meta.LocalIcon = item.AdminRouterIcon
			route.Meta.Icon = ""
		}
		return route
	})
}

// 构建路由树
func buildRouteTree(routes []*types.Route, parentId int64) []types.Route {
	var result []types.Route
	for _, route := range routes {
		if route.ParentId == parentId {
			subRoute := *route
			subRoute.Children = buildRouteTree(routes, route.Id)
			// 加入到此层级的结果集合
			result = append(result, subRoute)
		}
	}
	return result
}
